package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.web;

import java.text.ParseException;
import java.util.List;
import java.util.Objects;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.FlowProcessService;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpMigrateProcessModelDto;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpProcessInstanceQueryDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.exception.EventCallException;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowProcessInstanceTraceForMonitorVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.ProcessQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ResponseResult;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.RestTemplateRequestVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.eventconfig.EventExceptionDomain;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.model.EventResponse;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.FlowTaskTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.ProcessInstanceActionVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.ProcessInstanceQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.RuleActionAuditQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.RuleActionAuditVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.TaskTraceQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.*;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.TaskFormVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowEventExceptionRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowMonitorRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowProcessInstanceTraceRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTaskTraceRepository;

import io.swagger.annotations.Api;

import com.iwhalecloud.citybrain.flow.platform.manager.common.ErrorCode;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.ProcessInstanceActionEnum;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import static com.iwhalecloud.citybrain.flow.platform.manager.common.ErrorCode.BAD_REQUEST;

/**
 * Controller - 流程实例监控
 *
 * @author lilh
 * @date 2019-07-25 14:07
 */
@Slf4j
@Api(value = "流程实例监控", tags = {"流程实例监控"})
@RestController
@RequestMapping("/monitor")
public class FlowMonitorController {

    @Autowired
    private FlowProcessInstanceTraceRepository flowProcessInstanceTraceRepository;

    @Autowired
    private FlowMonitorRepository flowMonitorRepository;

    @Autowired
    private FlowTaskTraceRepository flowTaskTraceRepository;

    @Autowired
    private FlowEventExceptionRepository flowEventExceptionRepository;


    @Autowired
    private FlowProcessService flowProcessService;

    /**
     * 列表
     */
    @PostMapping("/processInstance/list")
    public ResponseResult list(@RequestBody ProcessInstanceQueryVo processInstanceQueryVo) throws ParseException {
        processInstanceQueryVo.setNeedCheckAuth(true);
        PageInfo<FlowProcessInstanceTraceForMonitorVo> pageInfos = new PageInfo<>(flowProcessInstanceTraceRepository.list(processInstanceQueryVo));
        return ResponseResult.success(pageInfos.getList()).setTotalCount((int) pageInfos.getTotal())
                .setPageNum(pageInfos.getPageNum()).setPageSize(pageInfos.getPageSize());
    }

    /**
     * 操作：挂起，解挂，终止，撤单
     */
    @PostMapping("/processInstance/doAction")
    public ResponseResult doAction(@RequestBody ProcessInstanceActionVo processInstanceActionVo) {
        if (Objects.isNull(ProcessInstanceActionEnum.getDesc(processInstanceActionVo.getAction()))) {
            return ResponseResult.fail(ErrorCode.PARAMETER_ERROR.errCode(), ErrorCode.PARAMETER_ERROR.errMessage());
        }

        if (CollectionUtils.isEmpty(processInstanceActionVo.getProcessInstanceIds())) {
            return ResponseResult.fail(ErrorCode.PARAMETER_ERROR.errCode(), ErrorCode.PARAMETER_ERROR.errMessage());
        }
        //迁移至最新版本
        if (Objects.equals(processInstanceActionVo.getAction(), ProcessInstanceActionEnum.UPGRADE.getCode())) {
            processInstanceActionVo.getProcessInstanceIds().forEach(processInstanceId -> {
                HttpMigrateProcessModelDto httpMigrateProcessModelDto = new HttpMigrateProcessModelDto();
                httpMigrateProcessModelDto.setProcessInstanceId(processInstanceId);
                log.info("UPGRADE Request:" + JSON.toJSONString(httpMigrateProcessModelDto));
                ResponseResult responseResult = flowProcessService.migrateToNewVersion(httpMigrateProcessModelDto);
                log.info("UPGRADE Result:" + JSON.toJSONString(responseResult));
            });
            return ResponseResult.success();
        }
        ResponseResult result = flowMonitorRepository.doAction(processInstanceActionVo);
        return result ;
    }

    /**
     * 流转日志列表
     */
    @PostMapping("/flowRecords/list")
    public ResponseResult listFlowRecords(@RequestBody ProcessQueryVo processQueryVo) {
        return ResponseResult.success(flowMonitorRepository.listFlowRecords(processQueryVo.getProcessInstanceId()));
    }


    /**
     * 获取任务关联的表单信息
     */
    @PostMapping("/task/showForm")
    public ResponseResult showForm(@RequestBody TaskFormVo taskFormVo) {
        return ResponseResult.success(flowMonitorRepository.showForm(taskFormVo.getTaskId()));

    }

    /**
     * 获取流程下已办理任务关联的表单信息
     */
    @PostMapping("/task/showFormsByInstanceId")
    public ResponseResult showFormsByInstanceId(@RequestBody ProcessQueryVo processQueryVo) {
        return ResponseResult.success(flowMonitorRepository.showFormsByInstanceId(processQueryVo.getProcessInstanceId(), processQueryVo.getBranchCode()));
    }

    /**
     * 任务通知列表
     */
    @PostMapping("/task/listNotice")
    public ResponseResult showNotice(@RequestBody TaskFormVo taskFormVo) {
        return ResponseResult.success(flowMonitorRepository.listNotices(taskFormVo.getTaskId()));
    }

    /**
     * 节点日志处理信息部分
     */
    @PostMapping("/task/listProcessItem")
    public ResponseResult showTaskProcessItem(@RequestBody TaskFormVo taskFormVo) {
        return ResponseResult.success(flowMonitorRepository.showTaskProcessItem(taskFormVo.getTaskId()));
    }

    /**
     * 任务列表
     */
    @PostMapping("/task/list")
    public ResponseResult listTaskTrace(@RequestBody TaskTraceQueryVo taskTraceQueryVo) {
        PageInfo<FlowTaskTraceVo> pageInfos = new PageInfo<>(flowTaskTraceRepository.listTaskTraces(taskTraceQueryVo));
        return ResponseResult.success(pageInfos.getList()).setTotalCount((int) pageInfos.getTotal())
                .setPageNum(pageInfos.getPageNum()).setPageSize(pageInfos.getPageSize());
    }

    /**
     * 根据roleId/positionId/orgId获取对应的人员名单
     */
    @PostMapping("/task/listUserNameByGroupId")
    public ResponseResult listUsersByGroupIdAndType(@RequestParam("type") String type, @RequestParam("groupId") String groupId) {
        return ResponseResult.success(flowTaskTraceRepository.listUserNameByGroupIdAndType(type, groupId));
    }

    /**
     * 规格操作监控列表查询
     *
     * @return
     */
    @PostMapping("/ruleAction/list")
    public ResponseResult listRuleActionAuditLog(@RequestBody RuleActionAuditQueryVo vo) {
        PageInfo<RuleActionAuditVo> pageInfo = flowMonitorRepository.listRuleActionAudit(vo);
        return ResponseResult.success(pageInfo.getList()).setTotalCount((int) pageInfo.getTotal())
                .setPageNum(pageInfo.getPageNum()).setPageSize(pageInfo.getPageSize());
    }

    /**
     * 任务节点事件异常信息列表查询
     */
    @PostMapping("/eventException/list")
    public ResponseResult listFlowEventException(@RequestBody ProcessQueryVo processQueryVo) {
        PageInfo<EventExceptionDomain> pageInfos = new PageInfo<>(flowEventExceptionRepository.queryEventExceptionList(processQueryVo));
        return ResponseResult.success(pageInfos.getList()).setTotalCount((int) pageInfos.getTotal())
                .setPageNum(pageInfos.getPageNum()).setPageSize(pageInfos.getPageSize());
    }

    /**
     * 任务节点事件异常信息补偿接口
     */
    @PostMapping("/eventException/restTemplateRequest")
    public ResponseResult restTemplateRequest(@RequestBody RestTemplateRequestVo vo) throws EventCallException {
        //boolean dealResult = flowEventExceptionRepository.restTemplateRequest(vo.getRequestUrl(), vo.getRequestJsonParams());
        EventResponse eventResponse = null;
        try {
            eventResponse = flowEventExceptionRepository.restTemplateRequest(vo.getRequestUrl(), vo.getRequestJsonParams(), vo.getId());
        } catch (Exception e) {
            return ResponseResult.fail(ErrorCode.BAD_REQUEST.errCode(), e.getMessage());
        }
        // 处理成功,更新补偿状态
        if (eventResponse != null && (eventResponse.isSuccess() || eventResponse.getData() != null)) {
            // 使用主键id更新记录,状态修改成已补偿
            EventExceptionDomain eventException = new EventExceptionDomain();
            eventException.setId(vo.getId());
            eventException.setStatus("1");
            int result = flowEventExceptionRepository.updateByPrimaryKeySelective(eventException);
            if (result > 0) {
                return ResponseResult.success(eventResponse);
            }
            return ResponseResult.fail(ErrorCode.BAD_REQUEST.errCode(), "接口调用成功,更新异常信息记录失败", null, eventResponse);
        }
        return ResponseResult.fail(ErrorCode.BAD_REQUEST.errCode(), "接口调用成功，接口返回失败", null, eventResponse);
    }

    @ApiOperation(value = "查询运行中流程变量")
    @PostMapping("/variable/running")
    public ResponseResult runningVariable(@RequestBody VariableQueryVo variableQueryVo) {
        PageInfo<VariableResult> pageInfos = new PageInfo<>(flowMonitorRepository.queryRunningVariableList(variableQueryVo));
        return ResponseResult.success(pageInfos.getList()).setTotalCount((int) pageInfos.getTotal())
                .setPageNum(pageInfos.getPageNum()).setPageSize(pageInfos.getPageSize());
    }

    @ApiOperation(value = "查询历史流程变量")
    @PostMapping("/variable/historic")
    public ResponseResult historicVariable(@RequestBody VariableQueryVo variableQueryVo) {
        PageInfo<VariableResult> pageInfos = new PageInfo<>(flowMonitorRepository.queryHistoricVariableList(variableQueryVo));
        return ResponseResult.success(pageInfos.getList()).setTotalCount((int) pageInfos.getTotal())
                .setPageNum(pageInfos.getPageNum()).setPageSize(pageInfos.getPageSize());
    }

    @ApiOperation(value = "修改运行中流程变量")
    @PostMapping("/variable/running/update")
    public ResponseResult updateRunningVariable(@RequestBody VariableResult variableResult) {
        try {
            return ResponseResult.success(flowMonitorRepository.updateRunningVariable(variableResult));
        } catch (Exception e) {
            return ResponseResult.fail(ErrorCode.BAD_REQUEST.errCode(), e.getMessage());
        }
    }

    @PostMapping("/eventException/processEventException")
    @ApiOperation(value = "批量补偿异常事件")
    public ResponseResult processEventException(@RequestBody ProcessQueryVo processQueryVo) {
        return flowEventExceptionRepository.processEventException(processQueryVo);
    }


}
